package org.goldenport.g3.channels.dropbox

import java.io.{InputStream, File}
import org.goldenport.wpath._
import org.goldenport.g3._
import org.goldenport.g3.atom._
import org.goldenport.g3.messages._
import org.goldenport.g3.adapters.{G3FileStoreAdapter, G3FileStoreDriver}
import com.dropbox.client._
import com.gargoylesoftware.htmlunit._
import com.gargoylesoftware.htmlunit.html._
import com.asamioffice.goldenport.io.UFile

/**
 * @since   Jul.  6, 2010
 * @version Aug. 30, 2010
 * @author  ASAMI, Tomoharu
 **/
class DropboxAdapter() extends G3FileStoreAdapter() {
  def create_Driver() = new DropboxDriver
}

class DropboxDriver extends G3FileStoreDriver {
  val DROPBOX = "http://dropbox.com/"
  private var dropbox_client: G3DropboxClient = _

  override def open() {
    val config = new java.util.HashMap[String, Any]
    config.put("server", "api.getdropbox.com")
    config.put("content_server", "api-content.getdropbox.com")
    config.put("port", 80L)
    config.put("consumer_key", "tll4tg54ws5b4y5")
    config.put("consumer_secret", "s2sc4z175ux3xi9")
    config.put("request_token_url", "http://api.getdropbox.com/0/oauth/request_token")
    config.put("access_token_url", "http://api.getdropbox.com/0/oauth/access_token")
    config.put("authorization_url", "http://api.getdropbox.com/0/oauth/authorize")
    val (username, password) = get_basic_auth(DROPBOX)
    val auth = new Authenticator(config)
    val url = auth.retrieveRequestToken(null)
    val tokenkey = auth.getTokenKey
    val tokensecret = auth.getTokenSecret
    login_form(url, username, password)
    auth.retrieveAccessToken("")
    //
    dropbox_client = new G3DropboxClient(config, auth)
    log_debug("Dropbox = " + dropbox_client)
  }

  private def login_form(url: String, username: String, password: String) {
    log_debug("dropbox auth = " + url)
    val webClient = new WebClient()
    webClient.setJavaScriptEnabled(false)
    val page = webClient.getPage(url).asInstanceOf[HtmlPage]
    val form = page.getForms().get(1).asInstanceOf[HtmlForm]
    val button = form.getInputByValue("Log in").asInstanceOf[HtmlSubmitInput]
    val emailField = form.getInputByName("login_email").asInstanceOf[HtmlTextInput]
    emailField.setValueAttribute(username);
    val passwordField = form.getInputByName("login_password").asInstanceOf[HtmlPasswordInput]
    passwordField.setValueAttribute(password);
    val page2 = button.click().asInstanceOf[HtmlPage]
    try {
      val form2 = page2.getForms().get(1).asInstanceOf[HtmlForm]
      val button2 = form2.getInputByValue("Allow").asInstanceOf[HtmlSubmitInput]
      button2.click()
    } catch {
      case e: ElementNotFoundException => log_debug("No allow button, must be already approved.")
      case e: IndexOutOfBoundsException => log_debug("No second form, must be already approved.")
    }
  }

  protected def create_File(container: WPath, filename: String) = {
    create_File(container, filename, "")
  }

  protected def create_File(container: WPath, filename: String, in: InputStream) = {
    create_file(container, filename, (file: File) => UFile.createFile(file, in))
  }

  protected def create_File(container: WPath, filename: String, string: String) = {
    create_file(container, filename, (file: File) => UFile.createFile(file, string, text_encoding))
  }

  private def create_file(container: WPath, filename: String, creator: File => Unit) = {
    val dirname = container.pathname
    val dir = work_directory()
    val file = new File(dir, filename)
    creator(file)
    dropbox_client.putFile("dropbox", dirname, file)
  }

  protected def read_Files(wpath: WPath): AnyRef = {
    val pathname = wpath.pathname
    val resp = dropbox_client.getFile("dropbox", pathname)
    if (resp == null) {
      error("not supported yet.")
    }
    resp.getStatusLine.getStatusCode match {
      case 200 => Blob(resp)
      case _ => error("not supported yet.")
    }
  }

  protected def write_File(wpath: WPath, id: String): AnyRef = {
    error("???")
    
  }

  protected def write_File(wpath: WPath, id: String, string: String): AnyRef = {
    error("???")
    
  }

  protected def write_File(wpath: WPath, id: String, in: InputStream): AnyRef = {
    error("???")
    
  }

  protected def remove_File(wpath: WPath): AnyRef = {
    error("???")
    
  }
}

trait DropboxContext extends G3Module {
  def dropbox(atom: Symbol): G3Channel = {
    add_channel_node(atom, context.createChannel(new DropboxAdapter()))
  }
}
